﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DataIntegrityChecker.Data;
using System.Threading;
using System.Globalization;
using System.Resources;

namespace DataIntegrityChecker
{
    public partial class MainForm : Form
    {
        private DataManager dataManager;
        private IntegrityChecker checker;
        private Proposition selectedProposition;
        private delegate void PropositionAddedToListDelegate(Proposition p);
        private delegate void UpdatePropositionListDelegate();
        private delegate void UpdateStatusDelegate(int current, int total);

        public MainForm()
        {
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(GlobalSettings.Language);
            InitializeComponent();
        }

        private void ChangeLanguage()
        {
            ResourceManager LocRM = new ResourceManager("DataIntegrityChecker.WinFormStrings", typeof(MainForm).Assembly);
            string text = LocRM.GetString("MessageBoxChangeLanguageText");
            string caption = LocRM.GetString("MessageBoxChangeLanguageCaption");

            DialogResult result = MessageBox.Show(text, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
            if(result == System.Windows.Forms.DialogResult.Yes)
                Application.Restart();
        }

        private void LoadData()
        {
            try
            {
                dataManager = new DataManager();
                GlobalSettings.OutputFile = null;
                dataManager.LoadData(GlobalSettings.InputFile, GlobalSettings.FirstRowHeaders);
                InitCombobox();
                InitIntegrityChecker();
                InitButtons();
            }
            catch (LoadDataException ex)
            {
                ResourceManager LocRM = new ResourceManager("DataIntegrityChecker.WinFormStrings", typeof(MainForm).Assembly);
                string caption = LocRM.GetString("MessageBoxLoadException");

                MessageBox.Show(ex.Message + "\n\n" + ex.InnerException.Message, caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
                dataManager = null;
            }
        }

        private void InitButtons()
        {
            saveAsToolStripMenuItem.Enabled = true;
            saveToolStripMenuItem.Enabled = true;
            toolStripButtonSave.Enabled = true;
            toolStripButtonStart.Enabled = true;
        }

        private void InitCombobox()
        {
            comboBoxColumnToCheck.Items.Clear();
            comboBoxColumnToCheck.Items.AddRange(dataManager.Headers);
        }

        private bool InitIntegrityChecker()
        {
            if (dataManager == null) return false;
            else
            {
                if (checker == null)
                {
                    checker = new IntegrityChecker(dataManager, -1, 0);
                    checker.RaisePropositionAddedEvent += new EventHandler<PropositionAddedEventArgs>(checker_RaisePropositionAddedEvent);
                    checker.RaisePropositionChangedEvent += new EventHandler<PropositionChangedEventArgs>(checker_RaisePropositionChangedEvent);
                    checker.RaisePropositionRemovedEvent += new EventHandler<PropositionRemovedEventArgs>(checker_RaisePropositionRemovedEvent);
                    checker.RaiseStatusChangedEvent += new EventHandler<StatusChangedArgs>(checker_RaiseStatusChangedEvent);
                }
                checker.Clear();
                checker.DataManager = dataManager;
                checker.ColumnToCheck = comboBoxColumnToCheck.SelectedIndex;
                checker.Cutoff = GlobalSettings.Cutoff;
                return true;
            }
        }

        private void buttonCheck_Click(object sender, EventArgs e)
        {
            if (comboBoxColumnToCheck.SelectedIndex == -1)
            {
                ResourceManager LocRM = new ResourceManager("DataIntegrityChecker.WinFormStrings", typeof(MainForm).Assembly);
                string text = LocRM.GetString("MessageBoxSelectColumnToCheckText");
                string caption = LocRM.GetString("MessageBoxSelectColumnToCheckCaption");

                MessageBox.Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
            }
            else if (InitIntegrityChecker())
            {
                checker.StartAsync();
            }
        }

        void checker_RaiseStatusChangedEvent(object sender, StatusChangedArgs e)
        {
            if (InvokeRequired)
            {
                UpdateStatusDelegate updateStatus = new UpdateStatusDelegate(UpdateStatus);
                try
                {
                    this.Invoke(updateStatus, new object[] { e.Current, e.Total });
                }
                catch (ObjectDisposedException) { }
                catch (InvalidOperationException) { }
            }
            else
            {
                UpdateStatus(e.Current, e.Total);
            }
        }

        void checker_RaisePropositionAddedEvent(object sender, PropositionAddedEventArgs e)
        {
            if (InvokeRequired)
            {
                PropositionAddedToListDelegate upd = new PropositionAddedToListDelegate(PropositionAddedToList);
                try
                {
                    this.Invoke(upd, new object[] { e.Proposition });
                }
                catch (ObjectDisposedException) { }
            }
            else
            {
                PropositionAddedToList(e.Proposition);
            }
        }

        void checker_RaisePropositionRemovedEvent(object sender, PropositionRemovedEventArgs e)
        {
            PropositionListChanged();
        }

        void checker_RaisePropositionChangedEvent(object sender, PropositionChangedEventArgs e)
        {
            PropositionListChanged();
        }

        private void PropositionListChanged()
        {
            if (InvokeRequired)
            {
                UpdatePropositionListDelegate upd = new UpdatePropositionListDelegate(UpdatePropositionList);
                try
                {
                    this.Invoke(upd, null);
                }
                catch (ObjectDisposedException) { }
            }
            else
            {
                UpdatePropositionList();
            }
        }

        private void PropositionAddedToList(Proposition p)
        {
            listViewPropositions.Items.Add(new PropositionListViewItem(p));
            ResourceManager LocRM = new ResourceManager("DataIntegrityChecker.WinFormStrings", typeof(MainForm).Assembly);
            string text = LocRM.GetString("StatusBarPropositionText");
            toolStripStatusLabelPropositionCount.Text = listViewPropositions.Items.Count + " " + text;
        }

        private void UpdateStatus(int current, int total)
        {
            toolStripStatusLabelCurrentRow.Text = current + " / " + total;
            toolStripButtonStart.Enabled = !checker.IsWorking;
            toolStripButtonStop.Enabled = checker.IsWorking;
        }

        private void UpdatePropositionList()
        {
            PropositionListViewItem selectedItem = (listViewPropositions.SelectedItems.Count > 0 ? (PropositionListViewItem)listViewPropositions.SelectedItems[0] : null);
            listViewPropositions.Items.Clear();
            foreach (Proposition p in checker.Propositions)
            {
                ListViewItem item = listViewPropositions.Items.Add(new PropositionListViewItem(p));
                item.Selected = (selectedItem != null && selectedItem.Proposition == p ? true : false);
                if (listViewPropositions.SelectedIndices.Count > 0)
                    listViewPropositions.EnsureVisible(listViewPropositions.SelectedIndices[0]);
            }
            ResourceManager LocRM = new ResourceManager("DataIntegrityChecker.WinFormStrings", typeof(MainForm).Assembly);
            string text = LocRM.GetString("StatusBarPropositionText");
            toolStripStatusLabelPropositionCount.Text = listViewPropositions.Items.Count + " " + text;
        }

        private void listViewPropositions_SelectedIndexChanged(object sender, EventArgs e)
        {
            ShowProposition();
        }

        private void ShowProposition()
        {
            if (listViewPropositions.SelectedItems.Count == 0)
            {
                textBoxProposedValue.Text = "";
                listViewSimilarRows.Items.Clear();
                selectedProposition = null;
            }
            else
            {
                selectedProposition = ((PropositionListViewItem)listViewPropositions.SelectedItems[0]).Proposition;
                textBoxProposedValue.Text = selectedProposition.ProposedValue;
                listViewSimilarRows.Items.Clear();
                foreach (DataIntegrityChecker.Data.DataRow row in selectedProposition.SimilarRows)
                {
                    ListViewItem item = new RowListViewItem(selectedProposition, row);
                    listViewSimilarRows.Items.Add(item);
                }

                listViewEqualRows.Items.Clear();
                foreach (DataIntegrityChecker.Data.DataRow row in selectedProposition.EqualRows)
                {
                    ListViewItem item = new RowListViewItem(selectedProposition, row);
                    listViewEqualRows.Items.Add(item);
                }
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.AutoUpgradeEnabled = true;
            openFileDialog.CheckFileExists = true;
            openFileDialog.Filter = "Tab-Delimited Text File | *.txt";
            openFileDialog.Title = "Select Input File";
            DialogResult result = openFileDialog.ShowDialog();
            if (result == System.Windows.Forms.DialogResult.OK)
            {
                GlobalSettings.InputFile = openFileDialog.FileName;
                LoadData();
            }
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.AutoUpgradeEnabled = true;
            saveFileDialog.Filter = "Tab-Delimited Text File | *.txt";
            saveFileDialog.Title = "Select Output File";
            DialogResult result = saveFileDialog.ShowDialog();
            if (result == System.Windows.Forms.DialogResult.OK)
            {
                GlobalSettings.OutputFile = saveFileDialog.FileName;
                dataManager.SaveData(GlobalSettings.OutputFile);
            }
        }

        private void toolStripButtonSettings_Click(object sender, EventArgs e)
        {
            FormSettings formSettings = new FormSettings(dataManager);
            formSettings.CutOff = GlobalSettings.Cutoff;
            formSettings.FirstRowHeaders = GlobalSettings.FirstRowHeaders;
            formSettings.Language = GlobalSettings.Language;
            if(checker != null){
            foreach (IDataConstraint c in checker.Constraints)
            {
                formSettings.Constraints.Add(c);
            }
                }
            if (formSettings.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                GlobalSettings.Cutoff = formSettings.CutOff;
                GlobalSettings.FirstRowHeaders = formSettings.FirstRowHeaders;
                if (GlobalSettings.Language != formSettings.Language)
                {
                    GlobalSettings.Language = formSettings.Language;
                    ChangeLanguage();
                }
                if (checker != null)
                {
                    checker.Constraints.Clear();
                    foreach (IDataConstraint c in formSettings.Constraints)
                    {
                        checker.Constraints.Add(c);
                    }
                }
            }
        }

        private void toolStripButtonDeleteProposition_Click(object sender, EventArgs e)
        {
            if (listViewPropositions.SelectedItems.Count == 0) return;

            ResourceManager LocRM = new ResourceManager("DataIntegrityChecker.WinFormStrings", typeof(MainForm).Assembly);
            string text = LocRM.GetString("MessageBoxDeletePropositionText");
            string caption = LocRM.GetString("MessageBoxDeletePropositionCaption");

            DialogResult result = MessageBox.Show(text, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);

            if (result == System.Windows.Forms.DialogResult.Yes)
            {
                PropositionListViewItem item = (PropositionListViewItem)listViewPropositions.SelectedItems[0];
                checker.RemoveProposition(item.Proposition);
            }
        }

        private void toolStripButtonStop_Click(object sender, EventArgs e)
        {
            checker.Stop();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (checker != null && checker.IsWorking)
                checker.Stop();
        }

        private void toolStripButtonDeleteSimilarRow_Click(object sender, EventArgs e)
        {
            if (selectedProposition == null) return;
            if (listViewSimilarRows.SelectedItems.Count == 0) return;

            ResourceManager LocRM = new ResourceManager("DataIntegrityChecker.WinFormStrings", typeof(MainForm).Assembly);
            string text = LocRM.GetString("MessageBoxDeleteSimilarRowText");
            string caption = LocRM.GetString("MessageBoxDeleteSimilarRowCaption");

            DialogResult result = MessageBox.Show(text , caption, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);

            if (result == System.Windows.Forms.DialogResult.Yes)
            {
                RowListViewItem selectedSimilarRow = (RowListViewItem)listViewSimilarRows.SelectedItems[0];
                selectedProposition.SimilarRows.Remove(selectedSimilarRow.DataRow);
                if (selectedProposition.SimilarRows.Count == 0) checker.RemoveProposition(selectedProposition);
                else checker.EditProposition(selectedProposition);
                ShowProposition();
            }
        }

        private void acceptAllPropositionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            checker.AcceptPropositions();
        }

        private void acceptSelectedPropositionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (selectedProposition == null) return;
            checker.AcceptProposition(selectedProposition);
        }

        private void toolStripButtonSave_Click(object sender, EventArgs e)
        {
            if (GlobalSettings.OutputFile == null)
            {
                ResourceManager LocRM = new ResourceManager("DataIntegrityChecker.WinFormStrings", typeof(MainForm).Assembly);
                string filter = LocRM.GetString("SaveFileDialogFilter");
                string title = LocRM.GetString("SaveFileDialogTitle");

                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.AutoUpgradeEnabled = true;
                saveFileDialog.DefaultExt = "*.txt";
                saveFileDialog.Filter = filter;
                saveFileDialog.Title = title;
                DialogResult result = saveFileDialog.ShowDialog();
                if (result == System.Windows.Forms.DialogResult.OK)
                {
                    GlobalSettings.OutputFile = saveFileDialog.FileName;
                    dataManager.SaveData(GlobalSettings.OutputFile);
                }
            }
            else
            {
                dataManager.SaveData(GlobalSettings.OutputFile);
            }
        }

        private void buttonApplyProposedValue_Click(object sender, EventArgs e)
        {
            ApplyProposedValue();
        }

        private void ApplyProposedValue()
        {
            if (checker == null || selectedProposition == null) return;
            selectedProposition.ProposedValue = textBoxProposedValue.Text;
            checker.EditProposition(selectedProposition);
        }

        private void toolStripButtonUseSimilarAsProposed_Click(object sender, EventArgs e)
        {
            if (checker == null || selectedProposition == null || listViewSimilarRows.SelectedItems.Count == 0) return;
            selectedProposition.ProposedValue = ((RowListViewItem)listViewSimilarRows.SelectedItems[0]).DataRow.Values[selectedProposition.ColumnToCorrect];
            checker.EditProposition(selectedProposition);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.Exit();
        }



    }
}
